<template>
  <div class="scan-container">
    <!-- 页面标题与简介 -->
    <div class="page-header">
      <h2 class="page-title">新建扫描任务</h2>
      <p class="page-description">提交新的漏洞扫描任务，支持多种漏洞类型的检测和分析</p>
    </div>
    
    <div class="content-grid">
      <!-- 左侧：任务提交表单 -->
      <div class="form-section">
        <el-card class="scan-form-card shadow-effect">
          <template #header>
            <div class="card-header">
              <span class="header-title">扫描任务配置</span>
              <div class="header-actions">
                <el-switch
                  v-model="useRealData"
                  active-text="真实数据"
                  inactive-text="模拟数据"
                  @change="onDataSourceChange"
                  class="data-source-switch"
                  :disabled="isScanning"
                />
                <el-button 
                  type="primary" 
                  plain
                  class="demo-btn"
                  @click="runDemoScan"
                  :disabled="isScanning"
                >
                  <el-icon><el-icon-Play /></el-icon>
                  演示模式
                </el-button>
              </div>
            </div>
          </template>
          
          <el-form 
            :model="scanForm" 
            :rules="scanRules" 
            ref="scanFormRef" 
            label-width="140px"
            class="scan-form"
          >
            <el-form-item label="目标URL/IP" prop="target">
              <el-input
                v-model="scanForm.target"
                placeholder="请输入要扫描的目标URL或IP地址"
                :disabled="isScanning"
                clearable
                prefix-icon="el-icon-Link"
                class="form-input-focus"
              />
              <div class="form-hint">支持HTTP/HTTPS协议的URL或IPv4地址</div>
            </el-form-item>
            
            <el-form-item label="扫描深度" prop="scanDepth">
              <el-slider
                v-model="scanForm.scanDepth"
                :min="1"
                :max="5"
                :disabled="isScanning"
                show-tooltip
                show-input
                marks="{1: '浅度', 5: '深度'}"
                class="depth-slider"
              />
              <div class="form-hint">
                <span :class="['depth-indicator', scanForm.scanDepth <= 2 ? 'quick' : scanForm.scanDepth <= 3 ? 'medium' : 'comprehensive']">
                  {{ scanForm.scanDepth <= 2 ? '快速模式' : scanForm.scanDepth <= 3 ? '标准模式' : '全面模式' }}
                </span>
                <span class="depth-desc">1-浅度扫描（快速），5-深度扫描（全面）</span>
              </div>
            </el-form-item>
            
            <el-form-item label="扫描类型" prop="scanTypes">
              <div class="scan-types-grid">
                <el-checkbox-group 
                  v-model="scanForm.scanTypes" 
                  :disabled="isScanning"
                  class="scan-types-group"
                >
                  <el-checkbox 
                    v-for="type in scanTypeOptions" 
                    :key="type.value"
                    :label="type.value" 
                    class="scan-type-checkbox transition-all hover:shadow-md"
                  >
                    <el-icon :class="`vuln-icon ${type.value}-icon`"><component :is="type.icon" /></el-icon>
                    <span class="vuln-name">{{ type.label }}</span>
                    <span class="vuln-desc">{{ type.description }}</span>
                  </el-checkbox>
                </el-checkbox-group>
              </div>
              <div class="scan-type-actions">
                <el-button 
                  v-if="scanForm.scanTypes.length < scanTypeOptions.length"
                  type="primary" 
                  size="small" 
                  @click="selectAllTypes"
                  :disabled="isScanning"
                  class="select-all-btn"
                >
                  全选
                </el-button>
                <el-button 
                  v-if="scanForm.scanTypes.length > 0"
                  type="info" 
                  size="small" 
                  @click="clearAllTypes"
                  :disabled="isScanning"
                  class="clear-all-btn"
                >
                  清除
                </el-button>
              </div>
            </el-form-item>
            
            <el-form-item>
              <div class="form-actions">
                <el-button 
                  type="primary" 
                  @click="submitScanTask" 
                  :loading="isScanning"
                  :disabled="isScanning"
                  class="primary-btn gradient-hover"
                  :icon="isScanning ? 'el-icon-Loading' : 'el-icon-Search'"
                >
                  {{ isScanning ? '扫描中...' : '开始扫描' }}
                </el-button>
                <el-button 
                  @click="resetForm" 
                  :disabled="isScanning"
                  class="reset-btn hover-effect"
                  icon="el-icon-Refresh"
                >
                  重置
                </el-button>
              </div>
            </el-form-item>
          </el-form>
        </el-card>
        
        <!-- 扫描提示卡片 -->
        <el-card class="scan-tips-card shadow-effect">
          <template #header>
            <div class="card-header">
              <el-icon><el-icon-Tips /></el-icon>
              <span>扫描提示</span>
            </div>
          </template>
          <ul class="tips-list">
            <li class="tip-item">
              <el-icon class="tip-icon info-icon"><el-icon-InfoFilled /></el-icon>
              <span>深度扫描可能需要较长时间，请耐心等待</span>
            </li>
            <li class="tip-item">
              <el-icon class="tip-icon success-icon"><el-icon-SuccessFilled /></el-icon>
              <span>建议先进行浅度扫描，再根据结果选择目标进行深度扫描</span>
            </li>
            <li class="tip-item warning-item">
              <el-icon class="tip-icon warning-icon"><el-icon-WarningFilled /></el-icon>
              <span>请勿对未授权的网站进行扫描，遵守相关法律法规</span>
            </li>
          </ul>
        </el-card>
      </div>
      
      <!-- 右侧：扫描进度 -->
      <div class="progress-section">
        <el-card v-if="currentTask" class="scan-progress-card shadow-effect">
          <!-- 确保即使没有数据也能正常显示 -->
          <template #header>
            <div class="card-header">
              <span>扫描进度</span>
              <el-button 
                type="text" 
                @click="refreshStatus"
                :disabled="isScanning"
                class="refresh-btn hover-effect"
                title="刷新状态"
              >
                <el-icon><Refresh /></el-icon>
                刷新
              </el-button>
            </div>
          </template>
          
          <div class="progress-info">
            <div class="info-grid">
              <div class="info-item">
                <label class="info-label">目标:</label>
                <span class="info-value target-value">{{ currentTask.target }}</span>
              </div>
              <div class="info-item">
                <label class="info-label">任务ID:</label>
                <span class="info-value task-id-value" @click="copyTaskId">{{ currentTask.task_id }}</span>
              </div>
              <div class="info-item">
                <label class="info-label">状态:</label>
                <el-badge 
                  :type="getStatusType(currentTask.status)"
                  :value="statusMap[currentTask.status] || currentTask.status"
                  class="status-badge"
                ></el-badge>
              </div>
            </div>
            
            <div class="progress-bar-container">
              <!-- 优化的进度条展示 -->
              <el-progress 
                :percentage="Math.round(currentTask.progress || 0)" 
                :status="getProgressStatus()"
                :color="getProgressColor()"
                show-text
                stroke-width="12"
                class="progress-bar"
                :format="(percentage) => `${percentage}%`"
              />
              
              <!-- 进度详情信息 -->
              <div class="progress-details">
                <div class="progress-metrics">
                  <div class="metric-item">
                    <span class="metric-label">当前进度:</span>
                    <span class="metric-value progress-percentage">
                      {{ Math.round(currentTask.progress || 0) }}%
                    </span>
                  </div>
                  <div class="metric-item">
                    <span class="metric-label">状态:</span>
                    <span class="metric-value status-text">{{ statusMap[currentTask.status] || currentTask.status }}</span>
                  </div>
                </div>
                
                <!-- 详细进度消息 -->
                <div v-if="currentTask.status === 'running' && currentTask.status_message" class="progress-message">
                  <el-icon class="message-icon"><InfoFilled /></el-icon>
                  <span>{{ currentTask.status_message }}</span>
                </div>
                
                <div class="progress-time-info">
                  <span class="progress-time">开始时间: {{ startTimeDisplay }}</span>
                  <span v-if="currentTask.status === 'completed'" class="progress-time">完成时间: {{ endTimeDisplay }}</span>
                  <span v-else-if="currentTask.progress > 0 && currentTask.progress < 100" class="progress-estimate">
                    预计剩余: {{ estimateRemainingTime() }}
                  </span>
                </div>
              </div>
            </div>
            
            <!-- 扫描日志 -->
            <div v-if="scanLogs.length > 0" class="scan-logs">
              <h4 class="logs-title">扫描日志</h4>
              <div class="logs-container" ref="logsContainer">
                <div 
                  v-for="(log, index) in scanLogs" 
                  :key="index" 
                  class="log-item"
                  :class="`log-${log.type}`"
                >
                  <el-icon :class="`log-icon log-icon-${log.type}`">
                    <component :is="log.type === 'success' ? SuccessFilled : log.type === 'warning' ? WarningFilled : InfoFilled" />
                  </el-icon>
                  <span class="log-time">{{ log.time }}</span>
                  <span class="log-content">{{ log.message }}</span>
                </div>
              </div>
            </div>
          </div>
          
          <div class="progress-actions">
            <el-button 
              v-if="currentTask.status === 'completed'" 
              type="primary" 
              @click="viewResults"
              class="view-results-btn"
            >
                查看结果
              </el-button>
            <el-button 
              v-else-if="['pending', 'running'].includes(currentTask.status)" 
              type="danger" 
              @click="cancelScanTask"
              class="cancel-btn"
            >
              停止
              取消扫描
            </el-button>
            <el-button 
              v-if="currentTask.status === 'failed' " 
              type="warning" 
              @click="retryScan"
              class="retry-btn"
            >
              <el-icon><Refresh /></el-icon>
              重试
            </el-button>
          </div>
        </el-card>
        
        <!-- 空状态提示 -->
        <div v-else class="empty-progress">
          <el-empty 
            description="暂无扫描任务进行中"
            image-size="120"
          >
            <template #bottom>
              <el-button type="primary" @click="runDemoScan">
                <el-icon><Play /></el-icon>
                尝试演示模式
              </el-button>
            </template>
          </el-empty>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onUnmounted } from 'vue'
import { ElMessage, ElNotification, ElMessageBox } from 'element-plus'
// Element Plus 图标导入
import { Search, Document, View, Share, Command, Link, Play, Refresh, Loading, InfoFilled, SuccessFilled, WarningFilled } from '@element-plus/icons-vue'
import apiService from '../services/apiService.js'
import { useRouter } from 'vue-router'

// 扫描类型选项配置
const scanTypeOptions = [
  {
    value: 'sql_injection',
    label: 'SQL注入',
    description: '检测数据库注入漏洞',
    icon: Search
  },
  {
    value: 'xss',
    label: '跨站脚本',
    description: '检测XSS攻击漏洞',
    icon: Document
  },
  {
    value: 'info_leak',
    label: '信息泄露',
    description: '检测敏感信息泄露',
    icon: View
  },
  {
    value: 'csrf',
    label: 'CSRF攻击',
    description: '检测跨站请求伪造',
    icon: Share
  },
  {
    value: 'cmd_injection',
    label: '命令注入',
    description: '检测系统命令注入',
    icon: Command
  },
  {
    value: 'ssrf',
    label: '服务器请求伪造',
    description: '检测SSRF漏洞',
    icon: Link
  }
]

// 响应式数据
const scanForm = ref({
  target: '',
  scanDepth: 2,
  scanTypes: ['sql_injection', 'xss']
})

const scanRules = ref({
  target: [
    { required: true, message: '请输入目标URL或IP地址', trigger: 'blur' },
    {
      pattern: /^(https?:\/\/[^\s]+|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/, 
      message: '请输入有效的URL或IP地址', 
      trigger: 'blur'
    }
  ],
  scanTypes: [
    { required: true, message: '请至少选择一种扫描类型', trigger: 'change' }
  ]
})

const scanFormRef = ref(null)
const isScanning = ref(false)
const currentTask = ref(null)
const statusMap = ref({
  'pending': '等待中',
  'running': '运行中',
  'completed': '已完成',
  'failed': '失败',
  'canceled': '已取消'
})

// 数据模式
const useRealData = ref(!(apiService.useMockData?.value ?? false))

// 数据模式切换处理
const onDataSourceChange = (value) => {
  if (apiService.setUseMockData) {
    apiService.setUseMockData(!value)
  }
}

// 提交扫描任务
const submitScanTask = async () => {
  if (!scanFormRef.value) return
  
  // 表单验证
  try {
    await scanFormRef.value.validate()
    
    isScanning.value = true
    
    // 模拟或真实提交
    if (apiService.useMockData?.value || !apiService.submitScan) {
      // 模拟提交
      await mockSubmitScan()
    } else {
      // 真实提交
      await submitRealScan()
    }
  } catch (error) {
    console.error('提交扫描任务失败:', error)
    if (error !== false) { // 排除表单验证失败的情况
      ElMessage.error('提交失败，请稍后重试')
    }
  } finally {
    isScanning.value = false
  }
}

// 模拟提交扫描
const mockSubmitScan = async () => {
  return new Promise((resolve) => {
    ElMessage.success('扫描任务已提交')
    
    // 模拟任务ID
    const taskId = 'mock-task-' + Date.now()
    
    // 初始化任务状态
    currentTask.value = {
      task_id: taskId,
      target: scanForm.value.target,
      status: 'running',
      progress: 0,
      startedAt: new Date().toISOString(),
      scanDepth: scanForm.value.scanDepth,
      scanTypes: scanForm.value.scanTypes
    }
    
    // 模拟进度更新
    simulateProgressUpdate(taskId)
    
    resolve({ success: true, data: { task_id: taskId } })
  })
}

// 真实提交扫描
const submitRealScan = async () => {
  try {
    const response = await apiService.submitScan({
      target: scanForm.value.target,
      scanDepth: scanForm.value.scanDepth,
      scanTypes: scanForm.value.scanTypes
    })
    
    if (response.success && response.data?.task_id) {
      ElMessage.success('扫描任务已提交')
      
      // 设置当前任务
      currentTask.value = {
        task_id: response.data.task_id,
        target: scanForm.value.target,
        status: 'pending',
        progress: 0,
        startedAt: new Date().toISOString(),
        scanDepth: scanForm.value.scanDepth,
        scanTypes: scanForm.value.scanTypes
      }
      
      // 开始轮询任务状态
      startStatusPolling(response.data.task_id)
    }
    
    return response
  } catch (error) {
    console.error('真实提交扫描失败:', error)
    // 失败时回退到模拟模式
    ElMessage.warning('真实扫描失败，切换到模拟模式')
    if (apiService.setUseMockData) {
      apiService.setUseMockData(true)
      useRealData.value = false
    }
    await mockSubmitScan()
  }
}

// 模拟进度更新
const simulateProgressUpdate = (taskId) => {
  let progress = 0
  const interval = setInterval(() => {
    progress += Math.random() * 10
    
    if (currentTask.value && currentTask.value.task_id === taskId) {
      currentTask.value.progress = Math.min(progress, 100)
      
      if (progress >= 100) {
        currentTask.value.status = 'completed'
        clearInterval(interval)
        
        // 模拟完成后的延迟通知
        setTimeout(() => {
          ElNotification.success({
            title: '扫描完成',
            message: `目标 ${currentTask.value.target} 的扫描已完成`,
            duration: 4000
          })
        }, 500)
      }
    } else {
      clearInterval(interval)
    }
  }, 800)
}

// 声明进度计时器引用
const progressTimer = ref(null)

// 开始轮询任务状态 (统一使用progressTimer来避免冲突)
const startStatusPolling = (taskId) => {
  // 确保先清除之前的定时器
  stopPollingStatus()
  
  progressTimer.value = setInterval(async () => {
    if (!currentTask.value || currentTask.value.task_id !== taskId) {
      stopPollingStatus()
      return
    }
    
    try {
      const status = await apiService.getScanStatus(taskId)
      if (status) {
        currentTask.value = { ...currentTask.value, ...status }
        
        if (status.status === 'completed' || status.status === 'failed' || status.status === 'canceled') {
          stopPollingStatus()
          
          ElNotification[status.status === 'completed' ? 'success' : 'error']({
            title: status.status === 'completed' ? '扫描完成' : '扫描失败',
            message: `目标 ${currentTask.value.target} 的扫描${status.status === 'completed' ? '已完成' : '失败'}`,
            duration: 4000
          })
        }
      }
    } catch (error) {
      console.error('获取扫描状态失败:', error)
      // 失败后回退到模拟模式
      stopPollingStatus()
      mockStatusUpdate(taskId)
    }
  }, 2000)
}

// 模拟状态更新（当真实API失败时）
const mockStatusUpdate = (taskId) => {
  if (!currentTask.value || currentTask.value.task_id !== taskId) return
  
  ElMessage.warning('无法获取真实状态，显示模拟进度')
  simulateProgressUpdate(taskId)
}

// 刷新状态
const refreshStatus = () => {
  if (!currentTask.value) return
  
  if (apiService.useMockData?.value || !apiService.getScanStatus) {
    // 模拟刷新
    ElMessage.success('状态已刷新')
  } else {
    // 真实刷新
    apiService.getScanStatus(currentTask.value.task_id)
      .then(status => {
        if (status) {
          currentTask.value = { ...currentTask.value, ...status }
          ElMessage.success('状态已刷新')
        }
      })
      .catch(error => {
        console.error('刷新状态失败:', error)
        ElMessage.error('刷新失败，请稍后重试')
      })
  }
}

// 运行演示扫描
const runDemoScan = () => {
  ElMessageBox.confirm(
    '将使用示例目标进行演示扫描，是否继续？',
    '演示模式',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'info'
    }
  ).then(() => {
    // 设置演示数据
    scanForm.value = {
      target: 'demo-target.example.com',
      scanDepth: 2,
      scanTypes: ['sql_injection', 'xss', 'info_leak']
    }
    
    // 自动提交
    setTimeout(() => {
      submitScanTask()
    }, 500)
  }).catch(() => {
    // 取消演示
  })
}

// 重置表单函数
  const resetForm = () => {
    scanFormRef.value.resetFields()
    ElMessage.success('表单已重置')
  }

  // 选择所有扫描类型
  const selectAllTypes = () => {
    scanForm.value.scanTypes = scanTypeOptions.map(type => type.value)
    ElMessage.success('已选择所有扫描类型')
  }

  // 清除所有扫描类型
  const clearAllTypes = () => {
    scanForm.value.scanTypes = []
    ElMessage.info('已清除所有扫描类型')
  }

  // 获取漏洞类型的中文标签
  const getVulnLabel = (value) => {
    const type = scanTypeOptions.find(t => t.value === value)
    return type ? type.label : value
  }

// 计算属性
const startTimeDisplay = computed(() => {
  if (!startTime.value) return '-'
  return new Date(startTime.value).toLocaleString('zh-CN')
})

const endTimeDisplay = computed(() => {
  if (!currentTask.value?.finished_at) return '-'
  return new Date(currentTask.value.finished_at).toLocaleString('zh-CN')
})

// 记录进度历史，用于估计剩余时间
const progressHistory = ref([])
// 错误显示标记，避免重复显示错误信息
const errorDisplayed = ref(false)

// 估计剩余时间
const estimateRemainingTime = () => {
  if (!currentTask.value || currentTask.value.progress <= 0) return '--'
  
  // 记录当前进度和时间
  const now = new Date()
  progressHistory.value.push({
    progress: currentTask.value.progress,
    time: now.getTime()
  })
  
  // 只保留最近的5个进度点
  if (progressHistory.value.length > 5) {
    progressHistory.value.shift()
  }
  
  // 需要至少2个进度点来计算
  if (progressHistory.value.length < 2) return '--'
  
  try {
    // 计算平均速度（百分比/秒）
    const first = progressHistory.value[0]
    const last = progressHistory.value[progressHistory.value.length - 1]
    const totalProgress = last.progress - first.progress
    const totalTime = (last.time - first.time) / 1000 // 转换为秒
    
    if (totalProgress <= 0 || totalTime <= 0) return '--'
    
    const avgSpeed = totalProgress / totalTime
    
    // 计算剩余进度所需时间
    const remainingProgress = 100 - last.progress
    const remainingSeconds = remainingProgress / avgSpeed
    
    // 格式化剩余时间
    if (remainingSeconds < 60) {
      return `${Math.ceil(remainingSeconds)}秒`
    } else if (remainingSeconds < 3600) {
      const minutes = Math.floor(remainingSeconds / 60)
      const seconds = Math.floor(remainingSeconds % 60)
      return `${minutes}分${seconds}秒`
    } else {
      const hours = Math.floor(remainingSeconds / 3600)
      const minutes = Math.floor((remainingSeconds % 3600) / 60)
      return `${hours}小时${minutes}分钟`
    }
  } catch (error) {
    console.error('计算剩余时间失败:', error)
    return '--'
  }
}





// 开始轮询任务状态
const startPollingStatus = () => {
  // 清除之前的定时器
  if (progressTimer.value) {
    clearInterval(progressTimer.value)
  }
  
  // 设置新的轮询定时器
  progressTimer.value = setInterval(async () => {
    if (currentTask.value) {
      try {
        const updatedTask = await apiService.getScanStatus(currentTask.value.task_id)
        
        // 更新扫描日志
        if (updatedTask.progress > (currentTask.value.progress || 0)) {
          scanLogs.value.push({
            time: new Date().toLocaleTimeString(),
            message: `扫描进度更新: ${updatedTask.progress}%`,
            type: 'info'
          })
        }
        
        // 任务状态变更处理
        if (updatedTask.status !== currentTask.value.status) {
          let statusMessage = ''
          let logType = 'info'
          
          switch(updatedTask.status) {
            case 'running':
              statusMessage = '扫描已开始'
              logType = 'info'
              break
            case 'completed':
              statusMessage = '扫描已完成'
              logType = 'success'
              ElNotification.success({
                title: '扫描完成',
                message: `目标 ${updatedTask.target} 的扫描已完成`,
                duration: 3000
              })
              break
            case 'failed':
              statusMessage = `扫描失败: ${updatedTask.error || '未知错误'}`
              logType = 'error'
              ElNotification.error({
                title: '扫描失败',
                message: statusMessage,
                duration: 3000
              })
              break
          }
          
          if (statusMessage) {
            scanLogs.value.push({
              time: new Date().toLocaleTimeString(),
              message: statusMessage,
              type: logType
            })
          }
        }
        
        currentTask.value = updatedTask
        
        // 如果任务完成或失败，停止轮询
        if (['completed', 'failed'].includes(updatedTask.status)) {
          stopPollingStatus()
          // 任务完成后跳转到结果页面
          if (updatedTask.status === 'completed' && updatedTask.scan_id) {
            setTimeout(() => {
              navigateToResults()
            }, 1000) // 延迟1秒跳转，让用户看到完成消息
          }
        }
      } catch (error) {
        console.error('获取扫描状态失败:', error)
        // 只在发生错误时显示一次消息，避免频繁提示
        if (!errorDisplayed.value) {
          ElMessage.error('获取扫描状态失败，请稍后刷新页面')
          errorDisplayed.value = true
        }
      }
    }
  }, 3000) // 每3秒轮询一次
}

// 停止轮询任务状态
const stopPollingStatus = () => {
  if (progressTimer.value) {
    clearInterval(progressTimer.value)
    progressTimer.value = null
  }
}

// 跳转到结果页面
const navigateToResults = () => {
  if (currentTask.value && currentTask.value.scan_id) {
    ElMessage.success('准备查看扫描结果...')
    router.push({
      path: '/results',
      query: { scanId: currentTask.value.scan_id }
    })
  }
}

// 查看扫描结果
const viewResults = () => {
  if (currentTask.value) {
      router.push({
        name: 'ResultsView',
        params: { taskId: currentTask.value.task_id }
      })
    }
  }
  
  
  
  // 取消扫描任务
  const cancelScanTask = async () => {
    if (!currentTask.value) return
    
    try {
      await apiService.cancelScan(currentTask.value.task_id)
      
      scanLogs.value.push({
        time: new Date().toLocaleTimeString(),
        message: '扫描任务已取消',
        type: 'warning'
      })
      
      ElMessage.success('扫描任务已取消')
      stopPollingStatus()
    } catch (error) {
      ElMessage.error(`取消扫描任务失败: ${error.message}`)
    }
  }
  
  // 重试扫描
  const retryScan = () => {
    // 复制当前任务的配置并重试
    const taskTarget = currentTask.value.target
    const taskDepth = scanForm.scanDepth
    const taskTypes = scanForm.scanTypes
    
    // 重置当前任务状态
    currentTask.value = null
    scanLogs.value = []
    
    // 重新设置表单值并提交
    scanForm.target = taskTarget
    scanForm.scanDepth = taskDepth
    scanForm.scanTypes = [...taskTypes]
    
    // 自动提交
    setTimeout(() => {
      submitScanTask()
    }, 500)
  }
  
  // 获取进度条状态
  const getProgressStatus = () => {
    if (!currentTask.value) return ''
    
    switch(currentTask.value.status) {
      case 'completed':
        return 'success'
      case 'failed':
        return 'exception'
      case 'running':
      case 'pending':
        return 'normal'
      default:
        return ''
    }
  }
  
  // 获取进度条颜色
  const getProgressColor = () => {
    if (!currentTask.value) return ''
    const progress = currentTask.value.progress || 0
    
    if (progress < 30) return '#1677ff'
    if (progress < 70) return '#e6a23c'
    return '#f56c6c'
  }
  
  // 获取状态标签类型
  const getStatusType = (status) => {
    switch(status) {
      case 'completed':
        return 'success'
      case 'failed':
        return 'danger'
      case 'running':
        return 'primary'
      case 'pending':
        return 'warning'
      default:
        return 'info'
    }
  }
  
  // 复制任务ID
  const copyTaskId = () => {
    if (!currentTask.value?.task_id) return
    
    navigator.clipboard.writeText(currentTask.value.task_id)
      .then(() => {
        ElMessage.success('任务ID已复制到剪贴板')
      })
      .catch(err => {
        ElMessage.error('复制失败，请手动复制')
        console.error('复制失败:', err)
      })
  }
  
  // 加载上次的扫描任务
  const loadLastTask = async () => {
    const lastTaskId = sessionStorage.getItem('currentTaskId')
    if (lastTaskId && !currentTask.value) {
      try {
        const task = await apiService.getScanStatus(lastTaskId)
        if (task && ['pending', 'running'].includes(task.status)) {
          currentTask.value = task
          startTime.value = new Date().toISOString()
          startPollingStatus()
          ElNotification.info({
            title: '恢复任务',
            message: '已恢复上次未完成的扫描任务',
            duration: 3000
          })
        }
      } catch (error) {
        console.error('加载上次任务失败:', error)
        // 清除无效的任务ID
        sessionStorage.removeItem('currentTaskId')
      }
    }
  }
  
  // 组件卸载时清理定时器
onUnmounted(() => {
  stopPollingStatus()
})

// 初始加载
loadLastTask()
</script>

<style scoped>
/* 全局样式 */
.scan-container {
  padding: 20px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  min-height: 100vh;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

/* 页面标题 */
.page-header {
  text-align: center;
  margin-bottom: 30px;
  padding: 20px;
  background: rgba(255, 255, 255, 0.95);
  border-radius: 16px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
  backdrop-filter: blur(10px);
}

.page-title {
  font-size: 36px;
  font-weight: 700;
  margin-bottom: 12px;
  background: linear-gradient(45deg, #1890ff, #722ed1);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  animation: titleGlow 3s ease-in-out infinite alternate;
}

@keyframes titleGlow {
  from {
    text-shadow: 0 0 10px rgba(24, 144, 255, 0.3);
  }
  to {
    text-shadow: 0 0 20px rgba(24, 144, 255, 0.6), 0 0 30px rgba(114, 46, 209, 0.4);
  }
}

.page-description {
  font-size: 16px;
  color: #666;
  line-height: 1.6;
  max-width: 800px;
  margin: 0 auto;
}

/* 内容布局 */
.content-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 30px;
  max-width: 1400px;
  margin: 0 auto;
}

.form-section, .progress-section {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

/* 卡片样式 */
.scan-form-card,
.scan-tips-card,
.scan-progress-card {
  background: #ffffff;
  border-radius: 16px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  border: none;
  overflow: hidden;
  position: relative;
}

.scan-form-card:hover,
.scan-tips-card:hover,
.scan-progress-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
}

/* 卡片头部 */
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 24px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  border-radius: 16px 16px 0 0;
  position: relative;
  overflow: hidden;
}

.card-header::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 50%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  animation: shimmer 3s infinite;
}

@keyframes shimmer {
  0% { left: -100%; }
  100% { left: 200%; }
}

.header-title {
  font-size: 20px;
  font-weight: 600;
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 8px;
}

.header-title {
  font-size: 18px;
  font-weight: 600;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  position: relative;
  z-index: 1;
}

.demo-btn {
  color: white;
  background: rgba(255, 255, 255, 0.2);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 8px;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  backdrop-filter: blur(5px);
}

.demo-btn:hover {
  background: rgba(255, 255, 255, 0.3);
  border-color: rgba(255, 255, 255, 0.5);
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}

.scan-form {
  padding: 24px;
}

.form-hint {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: #909399;
  margin-top: 8px;
}

.depth-indicator {
  padding: 4px 10px;
  border-radius: 12px;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  transition: all 0.3s ease;
}

.depth-indicator.quick {
  background-color: #e6f7ff;
  color: #1890ff;
}

.depth-indicator.medium {
  background-color: #fff7e6;
  color: #fa8c16;
}

.depth-indicator.comprehensive {
  background-color: #fff1f0;
  color: #f5222d;
}

.depth-desc {
  flex: 1;
}

.form-input-focus:focus {
  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
}

/* 扫描类型网格 */
.scan-types-group {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 12px;
  margin-bottom: 12px;
}

.scan-type-checkbox {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-radius: 10px;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  border: 1px solid #f0f0f0;
  background-color: #fff;
  position: relative;
  overflow: hidden;
}

.scan-type-checkbox::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(102, 126, 234, 0.1), transparent);
  transition: all 0.6s ease;
}

.scan-type-checkbox:hover::before {
  left: 100%;
}

.scan-type-checkbox:hover {
  background-color: #f5f9ff;
  border-color: #1890ff;
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.scan-type-checkbox.is-checked {
  background-color: #e6f7ff;
  border-color: #40a9ff;
  box-shadow: 0 4px 12px rgba(24, 144, 255, 0.2);
}

.scan-type-checkbox .vuln-icon {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  font-size: 18px;
  transition: all 0.3s ease;
  flex-shrink: 0;
}

.scan-type-checkbox:hover .vuln-icon {
  transform: scale(1.1);
}

.scan-type-checkbox .sql-icon { background-color: #e6f7ff; color: #1890ff; }
.scan-type-checkbox .xss-icon { background-color: #fff7e6; color: #fa8c16; }
.scan-type-checkbox .leak-icon { background-color: #fff1f0; color: #f5222d; }
.scan-type-checkbox .csrf-icon { background-color: #f6ffed; color: #52c41a; }
.scan-type-checkbox .cmd-icon { background-color: #f9f0ff; color: #722ed1; }
.scan-type-checkbox .ssrf-icon { background-color: #e6fffb; color: #13c2c2; }

.vuln-name {
  font-weight: 500;
  color: #333;
  min-width: 80px;
}

.vuln-desc {
  font-size: 12px;
  color: #909399;
  margin-left: auto;
  flex: 1;
  text-align: right;
}

.scan-type-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 12px;
}

/* 按钮样式 */
.form-actions {
  display: flex;
  gap: 16px;
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid #e4e7ed;
}

.primary-btn {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border: none;
  padding: 10px 24px;
  border-radius: 8px;
  font-size: 16px;
  font-weight: 500;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  overflow: hidden;
  color: white;
}

.primary-btn::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  transition: all 0.6s ease;
}

.primary-btn:hover::before {
  left: 100%;
}

.primary-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
}

.primary-btn:active {
  transform: translateY(0);
}

.reset-btn {
  border-radius: 8px;
  padding: 10px 24px;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  font-size: 16px;
}

.reset-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  background-color: #f5f7fa;
}

/* 扫描提示卡片样式 */
.scan-tips-card .card-header {
  background: linear-gradient(135deg, #6ab04c 0%, #2ecc71 100%);
}

.tips-list {
  padding: 16px 24px;
  margin: 0;
}

.tip-item {
  display: flex;
  align-items: flex-start;
  margin-bottom: 12px;
  padding: 8px 12px;
  background: #f8f9fa;
  border-radius: 8px;
  border-left: 4px solid #2ecc71;
}

.tip-item:last-child {
  margin-bottom: 0;
}

.tip-icon {
  margin-right: 12px;
  font-size: 16px;
  margin-top: 2px;
  flex-shrink: 0;
}

.tip-item:nth-child(3) {
  border-left-color: #f39c12;
}

.tip-item:nth-child(3) .tip-icon {
  color: #f39c12;
}

/* 扫描进度卡片样式 */
.progress-info {
  padding: 24px;
  position: relative;
}

.info-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
  margin-bottom: 24px;
}

.info-item {
  display: flex;
  align-items: center;
  padding: 16px;
  background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
  border-radius: 12px;
  border-left: 4px solid #667eea;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  overflow: hidden;
}

.info-item::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(102, 126, 234, 0.1), transparent);
  transition: all 0.6s ease;
}

.info-item:hover::before {
  left: 100%;
}

.info-item:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
}

.info-label {
  font-weight: 600;
  color: #2c3e50;
  margin-right: 16px;
  min-width: 80px;
  font-size: 14px;
}

.info-value {
  color: #7f8c8d;
  font-size: 14px;
  word-break: break-all;
  flex: 1;
}

.task-id-value {
  color: #667eea;
  cursor: pointer;
  font-family: 'Courier New', monospace;
  font-weight: 500;
  padding: 2px 8px;
  border-radius: 6px;
  background-color: rgba(102, 126, 234, 0.1);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  user-select: all;
}

.task-id-value:hover {
  color: #764ba2;
  background-color: rgba(118, 75, 162, 0.1);
  transform: scale(1.02);
}

.task-id-value.copied {
  background-color: rgba(82, 196, 26, 0.1);
  color: #52c41a;
  animation: pulse 0.6s ease;
}

@keyframes pulse {
  0% { transform: scale(1); }
  50% { transform: scale(1.05); }
  100% { transform: scale(1); }
}

.status-badge {
  font-size: 12px;
  padding: 4px 12px;
  border-radius: 16px;
  font-weight: 500;
  transition: all 0.3s ease;
}

.status-badge.running {
  background-color: #e6f7ff;
  color: #1890ff;
  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.2);
}

.status-badge.success {
  background-color: #f6ffed;
  color: #52c41a;
  box-shadow: 0 2px 8px rgba(82, 196, 26, 0.2);
}

.status-badge.error {
  background-color: #fff1f0;
  color: #ff4d4f;
  box-shadow: 0 2px 8px rgba(255, 77, 79, 0.2);
}

.status-badge.pending {
  background-color: #fff7e6;
  color: #fa8c16;
  box-shadow: 0 2px 8px rgba(250, 140, 22, 0.2);
}

.progress-bar-container {
  margin-bottom: 24px;
  position: relative;
}

.progress-bar {
  height: 16px;
  border-radius: 8px;
  margin-bottom: 16px;
  background-color: #f0f2f5;
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1);
  overflow: hidden;
}

.progress-bar :deep(.el-progress-bar__inner) {
  transition: width 0.8s cubic-bezier(0.4, 0, 0.2, 1);
  border-radius: 8px;
  background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
  background-size: 200% 100%;
  animation: gradientFlow 3s ease infinite;
  position: relative;
}

.progress-bar :deep(.el-progress-bar__inner)::after {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
  animation: shimmer 2s infinite;
}

.progress-bar :deep(.el-progress__text) {
  font-weight: bold;
  font-size: 14px;
  color: #667eea;
}

@keyframes gradientFlow {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

@keyframes shimmer {
  0% { left: -100%; }
  100% { left: 100%; }
}

.progress-details {
  font-size: 13px;
  color: #606266;
  margin-bottom: 16px;
}

.progress-message {
  margin-top: 12px;
  padding: 12px 16px;
  border-radius: 8px;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 12px;
  animation: slideIn 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 4px 12px rgba(59, 130, 246, 0.1);
  background: linear-gradient(135deg, #f0f9ff 0%, #e6f7ff 100%);
  border-left: 4px solid #3b82f6;
}

.progress-message.info {
  background: linear-gradient(135deg, #f0f9ff 0%, #e6f7ff 100%);
  border-left-color: #3b82f6;
  color: #1e40af;
}

.progress-message.success {
  background: linear-gradient(135deg, #f6ffed 0%, #f0f9f0 100%);
  border-left-color: #10b981;
  color: #065f46;
}

.progress-message.warning {
  background: linear-gradient(135deg, #fff7e6 0%, #fffaf0 100%);
  border-left-color: #f59e0b;
  color: #92400e;
}

.progress-message.error {
  background: linear-gradient(135deg, #fff1f0 0%, #fdf0f0 100%);
  border-left-color: #ef4444;
  color: #991b1b;
}

.message-icon {
  font-size: 18px;
  flex-shrink: 0;
}

.progress-message.info .message-icon { color: #3b82f6; }
.progress-message.success .message-icon { color: #10b981; }
.progress-message.warning .message-icon { color: #f59e0b; }
.progress-message.error .message-icon { color: #ef4444; }

@keyframes slideIn {
  from {
    opacity: 0;
    transform: translateX(-20px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.progress-metrics {
  display: flex;
  gap: 24px;
  margin-bottom: 16px;
  flex-wrap: wrap;
  padding: 16px;
  background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}

.metric-item {
  display: flex;
  align-items: center;
  gap: 8px;
  transition: all 0.3s ease;
  padding: 4px 12px;
  border-radius: 8px;
}

.metric-item:hover {
  background-color: rgba(102, 126, 234, 0.05);
  transform: translateY(-1px);
}

.metric-label {
  color: #606266;
  font-size: 13px;
  font-weight: 500;
}

.metric-value {
  font-weight: 600;
  color: #303133;
  font-size: 14px;
}

.metric-value.critical {
  color: #ff4d4f;
}

.metric-value.warning {
  color: #fa8c16;
}

.metric-value.info {
  color: #1890ff;
}

.metric-value.success {
  color: #52c41a;
}

.progress-percentage {
  font-size: 18px;
  font-weight: bold;
  color: #1890ff;
  margin-right: 8px;
}

.progress-time-info {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
  font-size: 13px;
  color: #606266;
  padding: 12px 0;
  border-top: 1px solid #e4e7ed;
}

.time-item {
  display: flex;
  align-items: center;
  gap: 6px;
}

.time-label {
  color: #909399;
}

.time-value {
  font-weight: 500;
  color: #303133;
}

.progress-estimate {
  color: #52c41a;
  font-weight: 600;
}

/* 扫描日志样式 */
.scan-logs {
  border-top: 1px solid #e4e7ed;
  padding: 20px 24px 0;
}

.logs-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid #f0f0f0;
}

.logs-title {
  font-size: 16px;
  font-weight: 600;
  color: #2c3e50;
  display: flex;
  align-items: center;
  gap: 8px;
}

.logs-title::before {
  content: '';
  width: 4px;
  height: 20px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 2px;
}

.logs-stats {
  display: flex;
  gap: 12px;
}

.log-count {
  font-size: 12px;
  color: #666;
  background-color: #f0f2f5;
  padding: 4px 10px;
  border-radius: 12px;
  font-weight: 500;
  transition: all 0.3s ease;
}

.log-count.error {
  background-color: #fff1f0;
  color: #ff4d4f;
}

.log-count.warning {
  background-color: #fff7e6;
  color: #fa8c16;
}

.logs-container {
  max-height: 300px;
  overflow-y: auto;
  background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
  border-radius: 12px;
  padding: 16px;
  box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.05);
  position: relative;
}

.logs-container::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 16px;
  background: linear-gradient(to bottom, #ffffff, transparent);
  z-index: 1;
  pointer-events: none;
}

.log-item {
  display: flex;
  margin-bottom: 8px;
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 13px;
  background: #ffffff;
  border-left: 3px solid #667eea;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  overflow: hidden;
  animation: fadeInUp 0.3s ease;
}

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.log-item::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(102, 126, 234, 0.05), transparent);
  transition: all 0.5s ease;
}

.log-item:hover::before {
  left: 100%;
}

.log-item:hover {
  transform: translateX(4px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

.log-item:last-child {
  margin-bottom: 0;
}

.log-time {
  color: #909399;
  margin-right: 16px;
  min-width: 80px;
  text-align: right;
  font-family: 'Courier New', monospace;
  font-weight: 500;
}

.log-content {
  color: #2c3e50;
  flex: 1;
  line-height: 1.5;
}

.log-icon {
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  margin-right: 8px;
  font-size: 12px;
  flex-shrink: 0;
}

.log-success {
  border-left-color: #27ae60;
  background: linear-gradient(135deg, #f6ffed 0%, #f0f9f0 100%);
}

.log-success .log-content {
  color: #27ae60;
}

.log-success .log-icon {
  background-color: #27ae60;
  color: white;
}

.log-error {
  border-left-color: #e74c3c;
  background: linear-gradient(135deg, #fff1f0 0%, #fdf0f0 100%);
}

.log-error .log-content {
  color: #e74c3c;
}

.log-error .log-icon {
  background-color: #e74c3c;
  color: white;
}

.log-warning {
  border-left-color: #f39c12;
  background: linear-gradient(135deg, #fff7e6 0%, #fffaf0 100%);
}

.log-warning .log-content {
  color: #f39c12;
}

.log-warning .log-icon {
  background-color: #f39c12;
  color: white;
}

.log-info {
  border-left-color: #3498db;
  background: linear-gradient(135deg, #f0f9ff 0%, #e6f7ff 100%);
}

.log-info .log-content {
  color: #3498db;
}

.log-info .log-icon {
  background-color: #3498db;
  color: white;
}

.progress-actions {
  display: flex;
  justify-content: flex-end;
  padding: 20px 24px 24px;
  gap: 16px;
  background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
  border-radius: 0 0 16px 16px;
}

.view-results-btn,
.cancel-btn,
.retry-btn,
.refresh-btn {
  border-radius: 8px;
  padding: 8px 20px;
  font-weight: 500;
  font-size: 14px;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  overflow: hidden;
  border: none;
  display: flex;
  align-items: center;
  gap: 8px;
}

.view-results-btn:hover,
.cancel-btn:hover,
.retry-btn:hover,
.refresh-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}

.view-results-btn {
  background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%);
  color: white;
}

.view-results-btn:hover {
  box-shadow: 0 8px 25px rgba(82, 196, 26, 0.3);
}

.view-results-btn::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  transition: all 0.6s ease;
}

.view-results-btn:hover::before {
  left: 100%;
}

.cancel-btn {
  background: linear-gradient(135deg, #ff4d4f 0%, #ff7875 100%);
  color: white;
}

.cancel-btn:hover {
  box-shadow: 0 8px 25px rgba(255, 77, 79, 0.3);
}

.cancel-btn::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  transition: all 0.6s ease;
}

.cancel-btn:hover::before {
  left: 100%;
}

.retry-btn {
  background: linear-gradient(135deg, #fa8c16 0%, #ffa940 100%);
  color: white;
}

.retry-btn:hover {
  box-shadow: 0 8px 25px rgba(250, 140, 22, 0.3);
}

.retry-btn::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  transition: all 0.6s ease;
}

.retry-btn:hover::before {
  left: 100%;
}

.refresh-btn {
  background: linear-gradient(135deg, #1890ff 0%, #40a9ff 100%);
  color: white;
}

.refresh-btn:hover {
  box-shadow: 0 8px 25px rgba(24, 144, 255, 0.3);
}

.refresh-btn::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  transition: all 0.6s ease;
}

.refresh-btn:hover::before {
  left: 100%;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.refresh-btn.spinning {
  animation: spin 1s linear infinite;
}

/* 空状态样式优化 */
.empty-progress {
  height: 400px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
  border-radius: 16px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.empty-progress:hover {
  box-shadow: 0 15px 50px rgba(0, 0, 0, 0.15);
  transform: translateY(-2px);
}

.empty-icon {
  font-size: 80px;
  color: #e0e0e0;
  margin-bottom: 20px;
  transition: all 0.3s ease;
  animation: float 3s ease-in-out infinite;
}

@keyframes float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-15px); }
}

.empty-title {
  font-size: 18px;
  font-weight: 600;
  color: #666;
  margin-bottom: 12px;
}

.empty-desc {
  font-size: 14px;
  color: #999;
  text-align: center;
  max-width: 300px;
  line-height: 1.6;
}

.empty-action {
  margin-top: 24px;
}

.empty-action .primary-btn {
  min-width: 160px;
}

/* 空状态样式 */
.empty-progress {
  height: 400px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #ffffff;
  border-radius: 16px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}

/* 响应式设计 */
@media (max-width: 1200px) {
  .content-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 768px) {
  .scan-container {
    padding: 12px;
  }
  
  .page-title {
    font-size: 24px;
  }
  
  .card-header {
    padding: 12px 16px;
  }
  
  .header-title {
    font-size: 16px;
  }
  
  .scan-form {
    padding: 16px;
  }
  
  .form-section, .progress-section {
    gap: 16px;
  }
  
  .scan-types-group {
    gap: 8px;
  }
  
  .form-actions {
    flex-direction: column;
  }
  
  .primary-btn, .reset-btn {
    width: 100%;
  }
  
  .progress-info {
    padding: 16px;
  }
  
  .progress-actions {
    padding: 0 16px 16px 16px;
    flex-direction: column;
  }
  
  .view-results-btn, .cancel-btn, .retry-btn {
    width: 100%;
  }
  
  .info-item {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }
  
  .info-label {
    min-width: auto;
  }
}

/* 滚动条样式 */
.logs-container::-webkit-scrollbar {
  width: 6px;
}

.logs-container::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

.logs-container::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 3px;
}

.logs-container::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

/* 动画效果 */
@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.scan-form-card,
.scan-tips-card,
.scan-progress-card {
  animation: fadeIn 0.5s ease;
}

.log-item {
  animation: fadeIn 0.3s ease;
}
</style>